热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数目|也就是_目标检测YOLOv5:添加漏检率和虚检率输出

篇首语:本文由编程笔记#小编为大家整理,主要介绍了目标检测YOLOv5:添加漏检率和虚检率输出相关的知识,希望对你有一定的参考价值。前言在目标

篇首语:本文由编程笔记#小编为大家整理,主要介绍了目标检测YOLOv5:添加漏检率和虚检率输出相关的知识,希望对你有一定的参考价值。



前言

在目标检测领域,衡量一个模型的优劣的指标往往是mAP,然而实际工程中,有时候更倾向于看漏检率和虚检率。YOLOv5的原始代码并没有这两个指标的输出,因此我想利用原始代码的混淆矩阵,输出这两个指标数值。


指标解释

漏检即原本有目标存在却没有检测出来,换句话说就是原本是目标却检测成了背景。
虚检(虚警)即原本没有目标却误认为有目标,换句话说就是原本是背景却检测成了目标。

首先来看YOLOv5原本输出的混淆矩阵,图中灰色覆盖的地方是原本输出的各类别,也就是输出的正例,最后一行和一列是背景类。
列是模型预测的结果,行是标签的真实结果。可以看到最后一行出现数值,表示出现了漏检;最后一列出现数值,则表示出现了虚检。


代码改进

现在来看YOLOv5输出的混淆矩阵代码部分,代码主要位于metrics.pyConfusionMatrix类中。

class ConfusionMatrix:
# Updated version of https://github.com/kaanakan/object_detection_confusion_matrix
def __init__(self, nc, conf=0.25, iou_thres=0.45):
"""
params nc: 数据集类别个数
params conf: 预测框置信度阈值
Params iou_thres: iou阈值
"""

self.matrix = np.zeros((nc + 1, nc + 1)) # +1的目的是添加背景类
self.nc = nc # number of classes
self.conf = conf
self.iou_thres = iou_thres
self.lou = 0
self.total = 0
self.xu = 0
def process_batch(self, detections, labels):
"""
Return intersection-over-union (Jaccard index) of boxes.
Both sets of boxes are expected to be in (x1, y1, x2, y2) format.
Arguments:
detections (Array[N, 6]), x1, y1, x2, y2, conf, class
labels (Array[M, 5]), class, x1, y1, x2, y2
Returns:
None, updates confusion matrix accordingly
"""

detections = detections[detections[:, 4] > self.conf] # 筛除置信度过低的预测框(和nms差不多)
gt_classes = labels[:, 0].int()
detection_classes = detections[:, 5].int()
iou = general.box_iou(labels[:, 1:], detections[:, :4])
x = torch.where(iou > self.iou_thres)
if x[0].shape[0]:
matches = torch.cat((torch.stack(x, 1), iou[x[0], x[1]][:, None]), 1).cpu().numpy()
if x[0].shape[0] > 1:
matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]]
else:
matches = np.zeros((0, 3))
n = matches.shape[0] > 0
m0, m1, _ = matches.transpose().astype(np.int16)
for i, gc in enumerate(gt_classes):
j = m0 == i
if n and sum(j) == 1:
# 如果sum(j)=1 说明gt[i]这个真实框被某个预测框检测到了
self.matrix[gc, detection_classes[m1[j]]] += 1 # correct
else:
# 如果sum(j)=0 说明gt[i]这个真实框没用被任何预测框检测到 也就是说这个真实框被检测成了背景框
self.matrix[self.nc, gc] += 1 # background FP
if n:
for i, dc in enumerate(detection_classes):
if not any(m1 == i):
self.matrix[dc, self.nc] += 1 # background FN
self.lou = sum(self.matrix[-1, :])
self.total = sum(sum(self.matrix))
self.xu = sum(self.matrix[:, -1])
def matrix(self):
return self.matrix
def plot(self, save_dir='', names=()):
try:
import seaborn as sn
# 按照每一列进行归一化
array = self.matrix / (self.matrix.sum(0).reshape(1, self.nc + 1) + 1E-6) # normalize
array[array < 0.005] &#61; np.nan # don&#39;t annotate (would appear as 0.00)
fig &#61; plt.figure(figsize&#61;(12, 9), tight_layout&#61;True)
sn.set(font_scale&#61;1.0 if self.nc < 50 else 0.8) # for label size
labels &#61; (0 < len(names) < 99) and len(names) &#61;&#61; self.nc # apply names to ticklabels
sn.heatmap(array, annot&#61;self.nc < 30, annot_kws&#61;"size": 8, cmap&#61;&#39;Blues&#39;, fmt&#61;&#39;.2f&#39;, square&#61;True,
xticklabels&#61;names &#43; [&#39;background FP&#39;] if labels else "auto",
yticklabels&#61;names &#43; [&#39;background FN&#39;] if labels else "auto").set_facecolor((1, 1, 1))
fig.axes[0].set_xlabel(&#39;True&#39;)
fig.axes[0].set_ylabel(&#39;Predicted&#39;)
fig.savefig(Path(save_dir) / &#39;confusion_matrix.png&#39;, dpi&#61;250)
except Exception as e:
pass
def print(self):
for i in range(self.nc &#43; 1):
print(&#39; &#39;.join(map(str, self.matrix[i])))

阅读代码可以发现&#xff0c;混淆矩阵再绘制时对每一列单独进行了归一化&#xff0c;那么再绘制之前&#xff0c;混淆矩阵存储了每一个预测结果和真实结果的数目。

于是我添加了三个属性self.louself.total &#61; 0self.xu &#61; 0&#xff0c;分别统计漏检目标数目&#xff0c;总目标数目和虚检目标数目。

漏检目标数目只需要将混淆矩阵最后一行相加&#xff0c;虚检目标数目只需要将混淆矩阵最后一列相加&#xff0c;总目标数目则将混淆矩阵所有数量相加。

然后在test.py中进行添加&#xff1a;

# Print speeds
t &#61; tuple(x / seen * 1E3 for x in (t0, t1, t0 &#43; t1)) &#43; (imgsz, imgsz, batch_size) # tuple
if not training:
print(&#39;Speed: %.1f/%.1f/%.1f ms inference/NMS/total per %gx%g image at batch-size %g&#39; % t)
# 计算漏检率
print("漏检样本数为&#xff1a;")
print(int(confusion_matrix.lou))
print("漏检率为&#xff1a;")
print(confusion_matrix.lou / confusion_matrix.total)
# 计算虚检率
print("虚检样本数为&#xff1a;")
print(int(confusion_matrix.xu))
print("虚检率为&#xff1a;")
print(confusion_matrix.xu / confusion_matrix.total)
# Plots
if plots:
confusion_matrix.plot(save_dir&#61;save_dir, names&#61;list(names.values()))
if wandb_logger and wandb_logger.wandb:
val_batches &#61; [wandb_logger.wandb.Image(str(f), caption&#61;f.name) for f in sorted(save_dir.glob(&#39;test*.jpg&#39;))]
wandb_logger.log("Validation": val_batches)
if wandb_images:
wandb_logger.log("Bounding Box Debugger/Images": wandb_images)

输出效果&#xff1a;


推荐阅读
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
author-avatar
极神bd韵
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有